﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Collections.ObjectModel;
using System.IO;
using System.IO.IsolatedStorage;
using CodeSample.Model;
using CodeSample.Utils;

namespace CodeSample
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        private ObservableCollection<string> cbbHeader;
        private ObservableCollection<SampleMan> samples;
        private List<string> languages;
        private DataProcessMan dataProcess;
        private string appearance = "";

        public ObservableCollection<SampleMan> LstVHeader
        {
            get { return samples; }
            set { samples = value; }
        }

        public ObservableCollection<string> CbbHeader
        {
            get { return cbbHeader; }
            set { cbbHeader = value; }
        }

        public MainWindow()
        {
            cbbHeader = new ObservableCollection<string>();
            samples = new ObservableCollection<SampleMan>();

            InitializeComponent();

            try
            {
                this.dataProcess = new DataProcessMan();
                this.dataProcess.GetSamples(ref samples);
                this.dataProcess.SortSamples(ref samples, SampleSortBy.LANGUAGE, SampleSortOption.ASCENDING);
                this.languages = dataProcess.GetLanguages(samples);
                this.SetLanguageComboBox(languages);
            }
            catch (Exception e)
            {
                MessageBox.Show(e.Message +"\n-Program will now exist", "Database Error", MessageBoxButton.OK, MessageBoxImage.Error);
                this.Close();
            }
        }

        private void SetLanguageComboBox(List<string> languages)
        {
            cbbHeader.Clear();
            cbbHeader.Add("All Languages");

            if (languages != null && languages.Count > 0)
            {
                foreach (string language in languages)
                {
                    cbbHeader.Add("--- " + language);
                }
            }
        }

        private void lstVResult_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            this.txtStatus.Text = "";
            int index = ((ListView)sender).SelectedIndex;

            if (this.lstVResult.SelectedIndex >= 0)
            {
                this.lblName.Content = this.samples[index].Language + ": " + this.samples[index].Name;
                this.rchtxtCode.SelectAll();
                this.rchtxtCode.Selection.Load(new MemoryStream(ASCIIEncoding.Default.GetBytes(this.samples[index].Code)), DataFormats.Rtf);
                this.txtDesc.Text = this.samples[index].Description.ToString();

                this.mniEditSample.IsEnabled = true;
                this.mniCopySampleCode.IsEnabled = true;
                this.mniRemoveSample.IsEnabled = true;
                if (this.lstVResult.SelectedItems.Count > 1)
                {
                    this.mniEditSample.Header = "Edit these samples";
                    this.mniRemoveSample.Header = "Remove these samples";
                    this.mniCopySampleCode.IsEnabled = false;
                }
                else
                {
                    this.mniEditSample.Header = "Edit sample";
                    this.mniRemoveSample.Header = "Remove sample";
                }
            }
            else
            {
                this.mniEditSample.IsEnabled = false;
                this.mniCopySampleCode.IsEnabled = false;
                this.mniRemoveSample.IsEnabled = false;
            }
        }

        private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            if (this.dataProcess != null)
                this.dataProcess.CloseConnection();
        }

        private void cbbLanguage_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (this.cbbLanguage.SelectedIndex >= 0)
            {
                this.GetSamplesByCategory();

                if (this.cbbLanguage.SelectedIndex == 0)
                    this.txtStatus.Text = "List samples from all languages";
                else
                {
                    this.txtStatus.Text = string.Format("List samples from {0}", this.cbbLanguage.SelectedItem.ToString().Substring(4));
                }
            }
        }

        private void txtSearch_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.Key == Key.Enter)
            {
                this.GetSamplesByCategory();
                this.dataProcess.Search(ref samples, this.txtSearch.Text.Trim());
                this.txtStatus.Text = "Search Done";
            }
        }

        private void GetSamplesByCategory()
        {
            try
            {
                if (this.cbbLanguage.SelectedIndex == 0)
                {
                    this.dataProcess.GetSamples(ref samples);
                    this.dataProcess.SortSamples(ref samples, SampleSortBy.LANGUAGE, SampleSortOption.ASCENDING);
                }
                else
                {
                    this.dataProcess.GetCategory(ref samples, this.cbbLanguage.SelectedItem.ToString().Substring(4));
                    this.dataProcess.SortSamples(ref samples, SampleSortBy.NAME, SampleSortOption.ASCENDING);
                }

                this.txtListCount.Text = "Samples: " + this.samples.Count;
            }
            catch (Exception e)
            {
                MessageBox.Show(e.Message + "\n-Program will now exist", "Database Error", MessageBoxButton.OK, MessageBoxImage.Error);
                this.Close();  
            }
        }

        public void InsertUpdateCallBack(string affactedSampleID, string statusMessage)
        {
            this.GetSamplesByCategory();
            this.languages = dataProcess.GetLanguages(this.samples);
            this.SetLanguageComboBox(this.languages);
            this.cbbLanguage.SelectedIndex = 0;

            int newIndex = this.dataProcess.GetIndexOfID(samples, affactedSampleID);
            if (newIndex >= 0)
                this.lstVResult.SelectedIndex = newIndex;

            this.txtStatus.Text = statusMessage + ". List updated";
        }

        public void MergeCallBack(string statusMessage)
        {
            this.GetSamplesByCategory();
            this.languages = dataProcess.GetLanguages(this.samples);
            this.SetLanguageComboBox(this.languages);
            this.cbbLanguage.SelectedIndex = 0;
            this.txtStatus.Text = statusMessage + ". List updated";
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            this.txtSearch.Text = "Search";
            this.GetSamplesByCategory();

            if (this.cbbLanguage.SelectedIndex >= 0)
            {
                this.GetSamplesByCategory();

                if (this.cbbLanguage.SelectedIndex == 0)
                    this.txtStatus.Text = "List samples from all languages";
                else
                {
                    this.txtStatus.Text = string.Format("List samples from {0}", this.cbbLanguage.SelectedItem.ToString().Substring(4));
                }
            }
        }

        private void mniAddSample_Click(object sender, RoutedEventArgs e)
        {
            InsertUpdateWindow insertSample = new InsertUpdateWindow(this.InsertUpdateCallBack, this.dataProcess);
            insertSample.Show();
        }

        private void mniEditSample_Click(object sender, RoutedEventArgs e)
        {
            this.EditSample();
        }

        private void EditSample()
        {
            if (this.lstVResult.SelectedItems.Count > 0)
            {
                foreach (var item in this.lstVResult.SelectedItems)
                {
                    InsertUpdateWindow updateSample = new InsertUpdateWindow((SampleMan)item, this.InsertUpdateCallBack, this.dataProcess);
                    updateSample.Show();
                }
            }
        }

        private void lstVResult_MouseDoubleClick(object sender, MouseButtonEventArgs e)
        {
            this.EditSample();
        }

        private void mniCopySampleCode_Click(object sender, RoutedEventArgs e)
        {
            this.rchtxtCode.Copy();
            this.txtStatus.Text = "Code copied to clipboard";
        }

        private void mniRemoveSample_Click(object sender, RoutedEventArgs e)
        {
            this.RemoveSample();
        }

        private void RemoveSample()
        {
            if (this.lstVResult.SelectedItems.Count > 0)
            {
                if (this.lstVResult.SelectedItems.Count == 1)
                {
                    if (MessageBox.Show("Are you sure to remove this code sample?\n'" + this.samples[this.lstVResult.SelectedIndex].Name + "'",
                        "Delete Conform", MessageBoxButton.YesNo, MessageBoxImage.Warning) == MessageBoxResult.Yes)
                    {
                        this.dataProcess.DeleteSample(this.samples[this.lstVResult.SelectedIndex]);
                        this.GetSamplesByCategory();
                        this.txtStatus.Text = "List updated";
                        this.lstVResult.Focus();
                    }
                }
                else
                {
                    if (MessageBox.Show("Are you sure to remove " + this.lstVResult.SelectedItems.Count.ToString() + " code samples?",
                        "Delete Conform", MessageBoxButton.YesNo, MessageBoxImage.Warning) == MessageBoxResult.Yes)
                    {
                        foreach (var item in this.lstVResult.SelectedItems)
                        {
                            this.dataProcess.DeleteSample((SampleMan)item);
                        }
                        this.GetSamplesByCategory();
                        this.txtStatus.Text = "List updated";
                        this.lstVResult.Focus();
                    }
                }
            }
        }

        private void lstVResult_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.Key == Key.Delete)
            {
                this.RemoveSample();
            }
            else if (e.Key == Key.Enter)
            {
                this.EditSample();
            }
        }

        private void cntxtmnAtSampleList_Opened(object sender, RoutedEventArgs e)
        {
            if (this.lstVResult.SelectedIndex >= 0)
            {
                this.cntxtmnEditSample.IsEnabled = true;
                this.cntxtmnRemoveSample.IsEnabled = true;
            }
            else
            {
                this.cntxtmnRemoveSample.IsEnabled = false;
                this.cntxtmnEditSample.IsEnabled = false;
            }
        }

        private void txtCodeDescription_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.Key != Key.LeftCtrl)
                this.EditSample();
        }

        private void mniAddSamplesFromFile_Click(object sender, RoutedEventArgs e)
        {
            //MessageBox.Show("Function not implement yet");
            MergingWindow merge = MergingWindow.GetInstance(this.MergeCallBack);
            merge.Show();
            merge.Activate();
        }

        private void mniAbout_Click(object sender, RoutedEventArgs e)
        {
            AboutBox aboutBox = AboutBox.GetInstance();
            aboutBox.Show();
            aboutBox.Activate();
        }

        private void mniBackground_Clicked(object sender, RoutedEventArgs e)
        {
            this.ChangeBackgroundColor(((MenuItem)sender));
        }

        private void ChangeBackgroundColor(MenuItem sender)
        {
            this.UnCheckAllThemeMenuItem();
            this.UnCheckAllBackgroundMenuItem();
            sender.IsChecked = true;
            this.lblName.Foreground = Brushes.Black;

            this.lstVResult.Foreground = Brushes.Black;

            this.grdMainGrid.Background = sender.Background;

            this.appearance = sender.Name;

            switch (sender.Header.ToString().ToUpper())
            {
                case "WHITE":
                    this.lblName.Foreground = Brushes.Black;
                    this.txtDesc.Foreground = Brushes.Black;
                    this.txtDesc.Background = Brushes.White;
                    this.txtSearch.Foreground = Brushes.Black;
                    this.txtSearch.Background = Brushes.White;

                    this.lstVResult.Background = Brushes.White;
                    this.rchtxtCode.Background = Brushes.White;
                    break;
                case "GRAY":
                case "GRAY GREEN":
                case "GREEN":
                case "DEEP GREEN":
                case "LIGHT BLUE":
                case "BLUE FACEBOOK":
                case "DEEP BLUE":
                case "PURPLE BLUE":
                case "PURPLE":
                case "ORANGE":
                case "ORANGE RED":
                case "RED":
                    this.lblName.Foreground = Brushes.White;
                    this.txtDesc.Foreground = Brushes.Black;
                    this.txtDesc.Background = Brushes.White;
                    this.txtSearch.Foreground = Brushes.Black;
                    this.txtSearch.Background = Brushes.White;

                    this.lstVResult.Background = Brushes.White;
                    this.rchtxtCode.Background = Brushes.White;
                    break;
            }
        }

        private void UnCheckAllBackgroundMenuItem()
        {
            this.mnibckgrndBlueFacebook.IsChecked = false;
            this.mnibckgrndDeepBlue.IsChecked = false;
            this.mnibckgrndDeepGreen.IsChecked = false;
            this.mnibckgrndGray.IsChecked = false;
            this.mnibckgrndGrayGreen.IsChecked = false;
            this.mnibckgrndGreen.IsChecked = false;
            this.mnibckgrndLightBlue.IsChecked = false;
            this.mnibckgrndOrange.IsChecked = false;
            this.mnibckgrndOrangeRed.IsChecked = false;
            this.mnibckgrndPurple.IsChecked = false;
            this.mnibckgrndPurpleBlue.IsChecked = false;
            this.mnibckgrndRed.IsChecked = false;
            this.mnibckgrndWhite.IsChecked = false;
            this.mniBackground.IsChecked = false;
        }

        private void UnCheckAllThemeMenuItem()
        {
            this.mnithmAppleTexture.IsChecked = false;
            this.mnithmGreenLeaves.IsChecked = false;
            this.mnithmWoodTexture.IsChecked = false;
            this.mnithmFlowers.IsChecked = false;
            this.mniTheme.IsChecked = false;
        }

        private void mniTheme_Checked(object sender, RoutedEventArgs e)
        {
            this.ChangeTheme(((MenuItem)sender));
        }

        private void ChangeTheme(MenuItem sender)
        {
            this.UnCheckAllBackgroundMenuItem();
            this.UnCheckAllThemeMenuItem();
            sender.IsChecked = true;

            ImageBrush imgBrush = new ImageBrush();
            SolidColorBrush transBlack = (SolidColorBrush)new BrushConverter().ConvertFromString("#B4000000");
            this.txtDesc.Background = transBlack;
            this.txtSearch.Background = transBlack;
            this.rchtxtCode.Background = Brushes.White;
            this.lstVResult.Background = Brushes.White;

            this.lblName.Foreground = Brushes.White;
            this.txtDesc.Foreground = Brushes.White;
            this.txtSearch.Foreground = Brushes.White;
            this.lstVResult.Foreground = Brushes.Black;

            this.appearance = sender.Name;

            switch (sender.Header.ToString().ToUpper())
            {
                case "APPLE TEXTURE":
                    imgBrush.ImageSource = new BitmapImage(new Uri("pack://application:,,,/Images/AppleTexture.jpg"));
                    this.txtDesc.Background = Brushes.Transparent;
                    this.txtSearch.Background = Brushes.Transparent;
                    this.rchtxtCode.Background = Brushes.Transparent;
                    this.lstVResult.Background = Brushes.Transparent;
                    this.txtDesc.Foreground = Brushes.Black;
                    this.txtSearch.Foreground = Brushes.Black;
                    this.lblName.Foreground = Brushes.Black;
                    break;
                case "WOOD TEXTURE":
                    imgBrush.ImageSource = new BitmapImage(new Uri("pack://application:,,,/Images/woodTexture.jpg"));
                    this.rchtxtCode.Background = (SolidColorBrush)new BrushConverter().ConvertFromString("#F5FFFFFF");
                    this.lstVResult.Background = (SolidColorBrush)new BrushConverter().ConvertFromString("#F5FFFFFF");
                    break;
                case "FLOWERS":
                    imgBrush.ImageSource = new BitmapImage(new Uri("pack://application:,,,/Images/Flowers.jpg"));
                    this.rchtxtCode.Background = (SolidColorBrush)new BrushConverter().ConvertFromString("#F5FFFFFF");
                    this.lstVResult.Background = (SolidColorBrush)new BrushConverter().ConvertFromString("#F5FFFFFF");
                    this.lstVResult.Background = transBlack;
                    this.lstVResult.Foreground = Brushes.White;
                    break;
                case "GREEN LEAVES":
                    imgBrush.ImageSource = new BitmapImage(new Uri("pack://application:,,,/Images/MacOSXLeopard.jpg"));
                    this.rchtxtCode.Background = (SolidColorBrush)new BrushConverter().ConvertFromString("#F5FFFFFF");
                    this.lstVResult.Background = transBlack;
                    this.lstVResult.Foreground = Brushes.White;
                    break;
            }
            this.grdMainGrid.Background = imgBrush;

            GC.WaitForPendingFinalizers();
            GC.Collect();
        }

        protected override void OnClosed(EventArgs e)
        {
            base.OnClosed(e);

            IsolatedStorageFile f = IsolatedStorageFile.GetUserStoreForAssembly();
            using (IsolatedStorageFileStream stream = new IsolatedStorageFileStream("Setting", FileMode.Create, f))
            using (StreamWriter writer = new StreamWriter(stream))
            {
                writer.WriteLine(this.appearance);
            }
        }

        protected override void OnInitialized(EventArgs e)
        {
            base.OnInitialized(e);

            IsolatedStorageFile f = IsolatedStorageFile.GetUserStoreForAssembly();
            using (IsolatedStorageFileStream stream = new IsolatedStorageFileStream("Setting", FileMode.OpenOrCreate, f))
            using (StreamReader reader = new StreamReader(stream))
            {
                this.appearance = reader.ReadLine();

                if (this.appearance != null)
                {
                    MenuItem mni = (MenuItem)this.FindName(this.appearance.Trim());

                    if (mni != null)
                    {
                        if (this.appearance.Contains("bckgrnd"))
                            this.ChangeBackgroundColor(mni);
                        else
                            this.ChangeTheme(mni);
                    }
                }
            }
        }

        private void mniCopySelection_Click(object sender, RoutedEventArgs e)
        {
            Clipboard.SetText(this.rchtxtCode.Selection.Text);
            this.txtStatus.Text = "Selected code copied to clipboard";
        }
    }
}

